//  Inside Microsoft Exchange 2007 Web Services
//  Appendix B
//
//  Copyright (c) 2007 David Sterling, Ben Spain, Mark Taylor, Huw Upshall, Michael Mainer.  
//  All rights reserved.
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using ProxyHelpers.EWS;

namespace CreateRecurringCalendarItem
{
    class Program
    {
        static void Main(string[] args)
        {
            ExchangeServiceBinding binding = new ExchangeServiceBinding();
            binding.Url = @"https://yourServer/ews/Exchange.asmx";
            binding.Credentials = new NetworkCredential(
                "username",
                "password",
                "domain");

            ItemIdType itemId = CreateRecurringCalendarItem(binding);
        }

        /// <summary>
        /// Create a daily recurring meeting using the Exchange Web Services
        /// best practice reguarding creation of new calendar items. (Listing B-11)
        /// </summary>
        /// <param name="binding">Binding to use for call</param>
        /// <returns>Item id of the new recurring master</returns>
        /// 
        public static ItemIdType CreateRecurringCalendarItem(
            ExchangeServiceBinding binding)
        {
            CalendarItemType newCalendarItem = new CalendarItemType();
            newCalendarItem.Subject = "Four Day Recurring Meeting";

            // Best Practices dictates that all DateTime structres be initialized with
            // DateTimeKind.Unspecified, including those that will be used in our
            // Recurrence pattern definition.
            //
            DateTime appointmentStartTime = new DateTime(
                2007, 11, 02, 08, 00, 00, DateTimeKind.Unspecified);
            DateTime recurrenceStartTime = new DateTime(
                2007, 11, 02, 00, 00, 00, DateTimeKind.Unspecified);

            newCalendarItem.Start = appointmentStartTime;
            newCalendarItem.End = appointmentStartTime.AddHours(1);
            newCalendarItem.StartSpecified = newCalendarItem.EndSpecified = true;

            // Construct the Recurrence pattern definition
            //
            DailyRecurrencePatternType pattern = new DailyRecurrencePatternType();
            pattern.Interval = 1;

            NumberedRecurrenceRangeType range = new NumberedRecurrenceRangeType();
            range.NumberOfOccurrences = 4;
            range.StartDate = recurrenceStartTime;

            newCalendarItem.Recurrence = new RecurrenceType();
            newCalendarItem.Recurrence.Item = pattern;
            newCalendarItem.Recurrence.Item1 = range;

            // Construct a TimeZoneType for a time zone that adheres to daylight
            // savings time, this requires us to fill in the optional Standard
            // and Daylight structures in our TimeZoneType.
            //
            TimeZoneType tzMST = new TimeZoneType();
            tzMST.BaseOffset = "PT7H";
            tzMST.Standard = new TimeChangeType();
            tzMST.Standard.Offset = "PT0H";

            // For the Time portion of a TimeChangeType, the 'date' is
            // unimportant, it will be omitted during serialization.
            //
            // Note: This method will require an IXmlSerializable interface
            // be defined on the TimeChangeType in order to ensure that
            // the .Time property values be serialized properly.  The code
            // for this interface can be found in Chapter 9 of 
            //  "Inside Microsoft Exchange Server 2007 Web Services."
            //
            tzMST.Standard.Time = new DateTime(
                2007, 01, 01, 02, 00, 00, DateTimeKind.Unspecified);

            // Define the day of the time change as a RelativeYearlyRecurrencePattern
            //
            RelativeYearlyRecurrencePatternType stdTimeChangeDay =
                new RelativeYearlyRecurrencePatternType();
            stdTimeChangeDay.DaysOfWeek = DayOfWeekType.Sunday.ToString();
            stdTimeChangeDay.DayOfWeekIndex = DayOfWeekIndexType.First;
            stdTimeChangeDay.Month = MonthNamesType.November;

            // The .Item property on the TimeChangeType is designed to hold either
            // a RelativeYearlyRecurrencePattern (which we have just created), or
            // an AbsoluteDateType.  Most time zones require the former, but a few
            // will require the later.
            //
            tzMST.Standard.Item = stdTimeChangeDay;

            // We must repeat this process for our Daylight change information as well
            tzMST.Daylight = new TimeChangeType();
            tzMST.Daylight.Offset = "-PT1H";
            tzMST.Daylight.Time = new DateTime(
                2007, 01, 01, 02, 00, 00, DateTimeKind.Unspecified);

            RelativeYearlyRecurrencePatternType dltTimeChangeDay =
                new RelativeYearlyRecurrencePatternType();
            dltTimeChangeDay.DaysOfWeek = DayOfWeekType.Sunday.ToString();
            dltTimeChangeDay.DayOfWeekIndex = DayOfWeekIndexType.Second;
            dltTimeChangeDay.Month = MonthNamesType.March;
            tzMST.Daylight.Item = dltTimeChangeDay;

            newCalendarItem.MeetingTimeZone = tzMST;

            // Construct the CreateItem request
            //
            CreateItemType createItemRequest = new CreateItemType();
            createItemRequest.SendMeetingInvitations =
                CalendarItemCreateOrDeleteOperationType.SendToNone;
            createItemRequest.SendMeetingInvitationsSpecified = true;
            createItemRequest.Items = new NonEmptyArrayOfAllItemsType();
            createItemRequest.Items.Items = new CalendarItemType[] { newCalendarItem };

            // Check the response for errors and if none occurred, return the id
            // of the newly created item.
            //
            CreateItemResponseType response = binding.CreateItem(createItemRequest);
            ItemInfoResponseMessageType responseMessage =
                response.ResponseMessages.Items[0] as ItemInfoResponseMessageType;
            if (responseMessage.ResponseCode != ResponseCodeType.NoError)
            {
                throw new Exception("CreateItem failed with response code " +
                          responseMessage.ResponseCode.ToString());
            }

            return responseMessage.Items.Items[0].ItemId;
        }

    }
}
